package org.chen.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.chen.enu.CommentFieldType;
import org.chen.model.CommentData;
import org.chen.model.CommentRule;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.util.*;

@Service
@Slf4j
public class SmartCommentService {

    @Autowired
    private ObjectMapper objectMapper;  // JSON处理

    @Autowired
    private CommentFieldPatternServiceImpl patternService;

    private Map<CommentFieldType, List<String>> getFieldPatterns() {
        Map<CommentFieldType, List<String>> patterns = new EnumMap<>(CommentFieldType.class);

        for (CommentFieldType fieldType : CommentFieldType.values()) {
            patterns.put(fieldType, patternService.getPatterns(fieldType));
        }

        return patterns;
    }

    /**
     * 分析表单，获取隐藏字段的名称
     */
    public Set<String> analyzeHiddenFieldNames(Element form) {
        Set<String> hiddenFieldNames = new HashSet<>();
        Elements hiddenInputs = form.select("input[type=hidden]");

        for (Element hidden : hiddenInputs) {
            String name = hidden.attr("name");
            if (!name.isEmpty()) {
                hiddenFieldNames.add(name);
            }
        }

        return hiddenFieldNames;
    }

    /**
     * 从当前表单获取隐藏字段的值
     */
    private Map<String, String> getHiddenFieldValues(Element form, Set<String> fieldNames) {
        Map<String, String> hiddenFields = new HashMap<>();

        for (String fieldName : fieldNames) {
            Element field = form.select(
                    String.format("input[name=%s]", fieldName)
            ).first();

            if (field != null) {
                hiddenFields.put(fieldName, field.attr("value"));
            }
        }

        return hiddenFields;
    }

    /**
     * 使用规则构建表单数据
     */
    public MultiValueMap<String, String> buildFormDataFromRule(
            CommentRule rule,
            CommentData commentData,
            Element currentForm) {

        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();

        // 添加主要字段
        if (rule.getCommentField() != null) {
            formData.add(rule.getCommentField(), commentData.getContent());
        }
        if (rule.getAuthorField() != null) {
            formData.add(rule.getAuthorField(), commentData.getAuthor());
        }
        if (rule.getEmailField() != null) {
            formData.add(rule.getEmailField(), commentData.getEmail());
        }
        if (rule.getUrlField() != null) {
            formData.add(rule.getUrlField(), commentData.getUrl());
        }

        try {
            // 获取隐藏字段名称列表
            Set<String> hiddenFieldNames = objectMapper.readValue(
                    rule.getHiddenFieldNames(),
                    new TypeReference<Set<String>>() {}
            );

            // 从当前表单获取隐藏字段的值
            Map<String, String> hiddenFieldValues = getHiddenFieldValues(currentForm, hiddenFieldNames);
            hiddenFieldValues.forEach(formData::add);

        } catch (JsonProcessingException e) {
            log.error("Error processing hidden fields", e);
        }

        return formData;
    }

    /**
     * 分析表单结构并返回字段映射
     */
    public Map<String, String> analyzeFormFields(Element form) {
        Map<String, String> fields = new HashMap<>();

        // 分析 input 元素
        Elements inputs = form.select("input");
        for (Element input : inputs) {
            analyzeInputElement(input, fields);
        }

        // 分析 textarea 元素
        Elements textareas = form.select("textarea");
        for (Element textarea : textareas) {
            analyzeTextareaElement(textarea, fields);
        }

        return fields;
    }

    private void analyzeInputElement(Element input, Map<String, String> fields) {
        String type = input.attr("type");
        String name = input.attr("name");
        String id = input.attr("id");

        if (name.isEmpty() && !id.isEmpty()) {
            name = id;
        }

        // 排除隐藏字段和提交按钮
        if ("hidden".equals(type) || "submit".equals(type)) {
            return;
        }

        // 确定字段类型
        CommentFieldType fieldType = determineFieldType(name, id);
        if (fieldType != null) {
            fields.put(fieldType.name().toLowerCase(), name);
        }
    }

    private void analyzeTextareaElement(Element textarea, Map<String, String> fields) {
        String name = textarea.attr("name");
        String id = textarea.attr("id");

        if (name.isEmpty() && !id.isEmpty()) {
            name = id;
        }

        CommentFieldType fieldType = determineFieldType(name, id);
        if (fieldType == CommentFieldType.COMMENT) {
            fields.put("comment", name);
        }
    }

    /**
     * 生成表单选择器
     */
    public String generateFormSelector(Element form) {
        StringBuilder selector = new StringBuilder("form");

        // 添加ID选择器
        if (form.hasAttr("id")) {
            selector.append("#").append(form.attr("id"));
        }

        // 添加class选择器
        if (form.hasAttr("class")) {
            String[] classes = form.attr("class").split("\\s+");
            for (String className : classes) {
                selector.append(".").append(className);
            }
        }

        // 添加action属性选择器
        if (form.hasAttr("action")) {
            selector.append("[action='").append(form.attr("action")).append("']");
        }

        return selector.toString();
    }

    /**
     * 智能构建表单数据
     */
    public MultiValueMap<String, String> buildSmartFormData(Element form, CommentData commentData) {
        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();

        // 处理所有input元素
        Elements inputs = form.select("input");
        for (Element input : inputs) {
            processInputElement(input, formData, commentData);
        }

        // 处理所有textarea元素
        Elements textareas = form.select("textarea");
        for (Element textarea : textareas) {
            processTextareaElement(textarea, formData, commentData);
        }

        // 处理所有隐藏字段
        processHiddenFields(form, formData);

        // 处理checkbox
        processCheckboxes(form, formData);

        return formData;
    }

    /**
     * 处理input元素
     */
    private void processInputElement(Element input, MultiValueMap<String, String> formData, CommentData commentData) {
        String type = input.attr("type");
        String name = input.attr("name");
        String id = input.attr("id");

        if (name.isEmpty() && !id.isEmpty()) {
            name = id;
        }

        // 跳过submit按钮
        switch (type) {
            case "submit" -> {
                formData.add(name, input.attr("value"));
                return;
            }


            // 处理隐藏字段
            case "hidden" -> {
                formData.add(name, input.attr("value"));
                return;
            }


            // 处理checkbox
            case "checkbox" -> {
                if (input.hasAttr("checked")) {
                    formData.add(name, input.attr("value"));
                }
                return;
            }
        }

        // 匹配字段类型并填充数据
        CommentFieldType fieldType = determineFieldType(name, id);
        if (fieldType != null) {
            String value = getValueForFieldType(fieldType, commentData);
            if (value != null) {
                formData.add(name, value);
            }
        }
    }

    /**
     * 处理textarea元素
     */
    private void processTextareaElement(Element textarea, MultiValueMap<String, String> formData, CommentData commentData) {
        String name = textarea.attr("name");
        String id = textarea.attr("id");

        if (name.isEmpty() && !id.isEmpty()) {
            name = id;
        }

        CommentFieldType fieldType = determineFieldType(name, id);
        if (fieldType == CommentFieldType.COMMENT) {
            formData.add(name, commentData.getContent());
        }
    }

    /**
     * 处理隐藏字段
     */
    private void processHiddenFields(Element form, MultiValueMap<String, String> formData) {
        Elements hiddenInputs = form.select("input[type=hidden]");
        for (Element hidden : hiddenInputs) {
            String name = hidden.attr("name");
            String value = hidden.attr("value");
            if (!name.isEmpty()) {
                formData.add(name, value);
            }
        }
    }

    /**
     * 处理checkbox
     */
    private void processCheckboxes(Element form, MultiValueMap<String, String> formData) {
        Elements checkboxes = form.select("input[type=checkbox]");
        for (Element checkbox : checkboxes) {
            String name = checkbox.attr("name");
            String value = checkbox.attr("value");

            // 处理常见的cookie同意checkbox
            formData.add(name, value);

        }
    }

    /**
     * 确定字段类型
     */
    private CommentFieldType determineFieldType(String name, String id) {
        name = name.toLowerCase();
        id = id.toLowerCase();

        Map<CommentFieldType, List<String>> patterns = getFieldPatterns();

        for (Map.Entry<CommentFieldType, List<String>> entry : patterns.entrySet()) {
            for (String pattern : entry.getValue()) {
                if (name.contains(pattern) || id.contains(pattern)) {
                    return entry.getKey();
                }
            }
        }

        return null;
    }

    /**
     * 根据字段类型获取对应的值
     */
    private String getValueForFieldType(CommentFieldType fieldType, CommentData commentData) {
        return switch (fieldType) {
            case COMMENT -> commentData.getContent();
            case AUTHOR -> commentData.getAuthor();
            case EMAIL -> commentData.getEmail();
            case URL -> commentData.getUrl();
            default -> null;
        };
    }
}